package p01_BeanFactory和ApplicationContext;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.lang.reflect.Field;
import java.util.Map;

/**
 * BeanFactory是最顶层的容器接口，表面上看只有个getBean方法经常用，真的是这样吗？
 */
@SpringBootApplication
public class _1_BeanFactory {
    public static void main(String[] args) throws Exception {
        /**
         * ConfigurableApplicationContext继承自ApplicationContext接口，ApplicationContext接口继承自BeanFactory
         * context.getBean()实际调用的BeanFactory的方法
         * BeanFactory能干嘛？
         *  表面上只有个getBean方法，实际上spring依赖注入，控制反转，生命周期都由其实现类DefaultListableBeanFactory实现
         */
        ConfigurableApplicationContext context = SpringApplication.run(_1_BeanFactory.class);

        /**
         *  DefaultListableBeanFactory的父类DefaultSingletonBeanRegistry维护了一个map，维护了所有单例bean
         *  该map由private final修饰的，无法被子类继承，可以通过反射得到该map
         */
        Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        singletonObjects.setAccessible(true);
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        Map<String, Object> map = (Map<String, Object>)singletonObjects.get(beanFactory);
        //打印所有单例bean
        System.out.println(map);
        /**
         * BeanFactory是ApplicationContext的父接口，它才是spring的核心容器
         * 而ApplicationContext的实现类都组合了它的功能,BeanFactory是ApplicationContext实现类的成员属性
         */
    }
}
